package com.nbsaas.boot.script;

import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;

public class HotReloadScriptEngine {

    private final Map<String, CachedScript> cache = new ConcurrentHashMap<>();
    private final Map<String, ScriptSource> sources = new HashMap<>();
    // Groovy 脚本引擎（通过 JSR-223 获取）
    private final ScriptEngine engine;

    public HotReloadScriptEngine(String language) {
        ServiceLoader<ScriptSource> loader = ServiceLoader.load(ScriptSource.class);
        for (ScriptSource source : loader) {
            sources.put(source.getPrefix(), source);
            System.out.println("加载脚本源: " + source.getPrefix());
        }
        javax.script.ScriptEngineManager factory = new javax.script.ScriptEngineManager();
        this.engine = factory.getEngineByName(language);
        if (!(engine instanceof Compilable)) {
            throw new IllegalStateException("当前脚本引擎不支持编译");
        }
    }

    public Object execute(String path) throws Exception {
        ScriptSource source = resolve(path);
        String script = source.loadScript(path);

        CachedScript cached = cache.get(path);
        if (cached == null) {
            cached = new CachedScript(compile(script), System.currentTimeMillis());
            cache.put(path, cached);
        }
        return cached.script.eval();
    }
    public Object execute(String path, Map<String, Object> context) throws Exception {
        ScriptSource source = resolve(path);
        String script = source.loadScript(path);

        CachedScript cached = cache.get(path);
        if (cached == null) {
            cached = new CachedScript(compile(script), System.currentTimeMillis());
            cache.put(path, cached);
        }
        // 创建绑定上下文
        Bindings bindings = cached.script.getEngine().createBindings();
        if (context != null) {
            bindings.putAll(context);
        }
        return cached.script.eval(bindings);
    }

    private ScriptSource resolve(String path) {
        return sources.values().stream()
                .filter(s -> path.startsWith(s.getPrefix()))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("未知路径协议: " + path));
    }

    private CompiledScript compile(String script) throws Exception {
        Compilable compilable = (Compilable) engine;
        return compilable.compile(script);
    }

    private record CachedScript(CompiledScript script, long timestamp) {
    }
}